package com.wumai.modernguilib.panel;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.wumai.modernguilib.component.BaseComponent;
import net.minecraft.client.gui.AbstractGui;

import java.util.HashMap;
import java.util.Map;

public class WeightBasedView extends BaseView {
    public enum Orientation {
        HORIZONTAL,
        VERTICAL
    }

    private Orientation orientation;
    private Map<BaseComponent, Float> weights = new HashMap<>();
    private float spacing = 0.01f;

    public WeightBasedView(Orientation orientation) {
        // 新的构造函数，不指定位置和大小，将由父容器或自动布局系统确定
        super(0, 0, 0, 0);
        this.orientation = orientation;
        this.spacing = 0.0f;
    }

    public WeightBasedView(int x, int y, int width, int height, Orientation orientation) {
        super(x, y, width, height);
        this.orientation = orientation;
    }

    @Override
    protected void renderBackground(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {

        // 绘制半透明背景
        AbstractGui.fill(matrixStack, x, y, x + width, y + height, 0x80000000);

        // 绘制边框
        AbstractGui.fill(matrixStack, x, y, x + width, y + 1, 0xFFFFFFFF); // 上边框
        AbstractGui.fill(matrixStack, x, y + height - 1, x + width, y + height, 0xFFFFFFFF); // 下边框
        AbstractGui.fill(matrixStack, x, y, x + 1, y + height, 0xFFFFFFFF); // 左边框
        AbstractGui.fill(matrixStack, x + width - 1, y, x + width, y + height, 0xFFFFFFFF); // 右边框
    }

    @Override
    protected void renderContent(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {

    }

    @Override
    protected void onChildAdded(BaseComponent component) {
        // 当通过addChild添加子组件时，默认权重为1.0
        if (!weights.containsKey(component)) {
            weights.put(component, 1.0f);
        }
    }
    
    @Override
    protected void onChildRemoved(BaseComponent component) {
        weights.remove(component);
    }

    /**
     * 添加带权重的子组件
     *
     * @param component 要添加的组件
     * @param weight    权重值，默认为1
     */
    public void addChild(BaseComponent component, float weight) {
        weights.put(component, weight);
        super.addChild(component);
    }

    /**
     * 添加带权重的子组件
     *
     * @param component 要添加的组件
     * @param weight    权重值，默认为1
     */
    public void addChild(BaseView component, float weight) {
        weights.put(component, weight);
        super.addChild(component);
    }

    /**
     * 添加带权重的子组件
     *
     * @param component 要添加的组件
     */
    @Override
    public void addChild(BaseComponent component) {
        addChild(component, 1.0f);
    }

    /**
     * 设置指定组件的权重
     *
     * @param component 要设置权重的组件
     * @param weight 权重值
     */
    public void setWeight(BaseComponent component, float weight) {
        if (children.contains(component)) {
            weights.put(component, weight);
        }
    }
    
    /**
     * 获取指定组件的权重
     *
     * @param component 要获取权重的组件
     * @return 组件的权重值，如果组件不存在则返回默认权重1.0
     */
    public float getWeight(BaseComponent component) {
        return weights.getOrDefault(component, 1.0f);
    }
    
    /**
     * 更新布局，根据权重重新计算各组件的位置和大小
     */
    public void updateLayout() {
        if (children.isEmpty()) {
            return;
        }

        float totalWeight = 0;
        for (BaseComponent child : children) {
            totalWeight += weights.getOrDefault(child, 1.0f);
        }

        if (totalWeight <= 0) {
            totalWeight = 1.0f; // 防止除零错误
        }

        if (orientation == Orientation.HORIZONTAL) {
            updateHorizontalLayout(totalWeight);
        } else {
            updateVerticalLayout(totalWeight);
        }
    }

    private void updateHorizontalLayout(float totalWeight) {
        int availableWidth = width - (int)(paddings[PaddingPosition.LEFT] * getCurrentScreenWidth()) - (int)(paddings[PaddingPosition.RIGHT] * getCurrentScreenWidth()) - (int)(Math.max(0, (children.size() - 1)) * spacing * getCurrentScreenWidth());
        int currentX = x + (int)(paddings[PaddingPosition.LEFT] * getCurrentScreenWidth());

        for (BaseComponent component : children) {
            float weight = weights.getOrDefault(component, 1.0f);
            int childWidth = (int)((weight / totalWeight) * availableWidth);
            component.setX(currentX);
            component.setY(y + (int)(paddings[PaddingPosition.TOP] * getCurrentScreenHeight()));
            component.setWidth(childWidth);
            component.setHeight(height - (int)(paddings[PaddingPosition.TOP] * getCurrentScreenHeight()) - (int)(paddings[PaddingPosition.BOTTOM] * getCurrentScreenHeight()));

            currentX += childWidth + (int)(spacing * getCurrentScreenWidth());
        }
    }

    private void updateVerticalLayout(float totalWeight) {
        int availableHeight = height - (int)(paddings[PaddingPosition.TOP] * getCurrentScreenHeight()) - (int)(paddings[PaddingPosition.BOTTOM] * getCurrentScreenHeight()) - (int)(Math.max(0, (children.size() - 1)) * spacing * getCurrentScreenHeight());
        int currentY = y + (int)(paddings[PaddingPosition.TOP] * getCurrentScreenHeight());

        for (BaseComponent component : children) {
            float weight = weights.getOrDefault(component, 1.0f);
            int childHeight = (int)((weight / totalWeight) * availableHeight);
            component.setX(x + (int)(paddings[PaddingPosition.LEFT] * getCurrentScreenWidth()));
            component.setY(currentY + (int)(paddings[PaddingPosition.TOP] * getCurrentScreenHeight()));
            component.setWidth(width - (int)(paddings[PaddingPosition.LEFT] - paddings[PaddingPosition.RIGHT]));
            component.setHeight(childHeight);

            currentY += childHeight + (int)(spacing * getCurrentScreenHeight());
        }
    }

    public Orientation getOrientation() {
        return orientation;
    }

    public void setOrientation(Orientation orientation) {
        this.orientation = orientation;
        updateLayout();
    }

    public float getSpacing() {
        return spacing;
    }

    public void setSpacing(float spacing) {
        this.spacing = spacing;
        updateLayout();
    }
}